home *** CD-ROM | disk | FTP | other *** search
- /*************************************************
- * RandomFinderStrings.c
- *
- * This INIT installs a patch on DrawString that
- * will tweak strings drawn by the Finder. If
- * CurApName != "/pFinder" or if the option key
- * is down then a normal DrawString takes place.
- * If we are in the Finder then a modified version
- * of the string is drawn: the upper/lower case
- * of the letters might be changed, the string
- * might be flipped backwards, all the vowels
- * might get accent marks, etc.
- *
- * You can add to the list of effects by adding
- * an item to the Effects enum and the main
- * switch statement in MyDrawString. If your
- * effects need globals, put them in the
- * PatchGlobals struct and initialize them in main.
- *
- * In Think C, set the Project Type to Code
- * Resource, the File Type to INIT, the Creator
- * to anything, the Type to INIT, the ID to
- * something like 55 (55 will work but it
- * doesn't have to be 55), turn Custom Header
- * ON and Attrs to 20 (purgeable) and Multi
- * Segment OFF.
- *
- * Mike Scanlin. 24 Jan 1993.
- ************************************************/
-
- /*************************************************
- * defines
- ************************************************/
- #define _DrawString 0xA884
-
- enum Effects {
- UpperCase = 0,
- LowerCase,
- ReverseCase,
- RandomCase,
- BackwardsLetters,
- AccentedVowels,
- NoVowels,
- PigLatin,
- NumEffects /* must be last */
- };
-
- /* Turn these all on for maximum randomness */
- #define DO_CASE_CHANGES 1
- #define BACKWARDS_LETTERS 1
- #define ACCENTED_VOWELS 1
- #define NO_VOWELS 1
- #define PIG_LATIN 0
-
- #define ALWAYS_TWEAK_STRING 1
-
- #if ALWAYS_TWEAK_STRING && !(DO_CASE_CHANGES || \
- BACKWARDS_LETTERS || ACCENTED_VOWELS || NO_VOWELS)
- not!
- /* Generate a compile time error if you set
- * up an impossible situation. You need to
- * have at least one effect enabled if
- * ALWAYS_TWEAK_STRING is enabled.
- */
- #endif
-
-
- /*************************************************
- * typedefs
- ************************************************/
- typedef pascal void (*DSProcPtr)(Str255 *theStringPtr);
-
- typedef struct PatchGlobals {
- DSProcPtr pgOldDS;
- } PatchGlobals, *PatchGlobalsPtr;
-
-
- /*************************************************
- * prototypes
- ************************************************/
- void main(void);
- void StartPatchCode(void);
- pascal void MyDrawString(Str255 *theStringPtr);
- short abs(short n);
- void EndPatchCode(void);
-
-
- /*************************************************
- * main
- *
- * Gets some memory in the system heap and
- * installs the DrawString patch (as well as
- * allocating and initializing the patch globals).
- * This is the only routine that gets executed at
- * startup time (by the INIT mechanism).
- *
- * The block of memory that main allocates will
- * look like this when main has finished:
- *
- * +--------------------+
- * | PatchGlobals |
- * +--------------------+
- * | StartPatchCode() |
- * DS trap addr -> +--------------------+
- * | MyDrawString() |
- * +--------------------+
- * | abs() |
- * +--------------------+
- * | EndPatchCode() |
- * +--------------------+
- *
- ************************************************/
- void main()
- {
- Ptr patchPtr;
- PatchGlobalsPtr pgPtr;
- long codeSize, offset;
-
- /* try and get some memory in the system heap
- * for code and globals */
- codeSize = (long) EndPatchCode -
- (long) StartPatchCode;
- patchPtr = NewPtrSys(codeSize +
- sizeof(PatchGlobals));
- if (!patchPtr)
- return; /* out of memory--abort patching */
-
- /* initialize the patch globals at the
- * beginning of the block */
- pgPtr = (PatchGlobalsPtr) patchPtr;
- pgPtr->pgOldDS = (DSProcPtr)
- GetTrapAddress(_DrawString);
-
- /* move the code into place after the globals */
- BlockMove(StartPatchCode, patchPtr +
- sizeof(PatchGlobals), codeSize);
-
- /* set the patches */
- patchPtr += sizeof(PatchGlobals);
- offset = (long) MyDrawString -
- (long) StartPatchCode;
- SetTrapAddress((long) patchPtr + offset,
- _DrawString);
- }
-
-
- /*************************************************
- * StartPatchCode
- *
- * Dummy proc to mark the beginning of the code
- * for the patches. Make sure all of your patch
- * code is between here and EndPatchCode.
- ************************************************/
- void StartPatchCode()
- {
- }
-
-
- /*************************************************
- * MyDrawString
- *
- * Head patch on DrawString that randomly tweaks
- * the string to be drawn if the current
- * application is the Finder and the Option key
- * is not down.
- ************************************************/
- pascal void MyDrawString(Str255 *theStringPtr)
- {
- Str255 copyOfString;
- EventRecord theEvent;
- PatchGlobalsPtr pgPtr;
- Byte *p, *inputPtr;
- short rand;
- Byte i, ch;
-
- /* if we're not in the Finder then exit */
- if (*(char *) &CurApName != 6 ||
- *(long *) ((Ptr) &CurApName + 1) != 'Find' ||
- *(short *) ((Ptr) &CurApName + 5) != 'er' )
- goto DontDoAnything;
-
- /* if the option key is down then exit */
- OSEventAvail(0, &theEvent);
- if (theEvent.modifiers & optionKey)
- goto DontDoAnything;
-
- /* we're in the Finder so do something to a
- * copy of the string (unless it's zero-length) */
- if (i = *(Byte *) theStringPtr) {
- p = (Byte *) ©OfString;
- BlockMove(theStringPtr, p++, i + 1);
-
- TryAgain:
-
- switch (abs(Random()) % NumEffects) {
-
- #if DO_CASE_CHANGES
- case UpperCase:
- /* force all letters to upper case */
- do {
- if (*p >= 'a' && *p <= 'z')
- *p -= 'a' - 'A';
- p++;
- } while (--i);
- break;
-
- case LowerCase:
- /* force all letters to lower case */
- do {
- if (*p >= 'A' && *p <= 'Z')
- *p += 'a' - 'A';
- p++;
- } while (--i);
- break;
-
- case ReverseCase:
- /* flip the upper/lower case of each letter */
- do {
- if (*p >= 'a' && *p <= 'z')
- *p -= 'a' - 'A';
- else if (*p >= 'A' && *p <= 'Z')
- *p += 'a' - 'A';
- p++;
- } while (--i);
- break;
-
- case RandomCase:
- /* randomly set the case of each letter */
- do {
- /* force to lower case */
- if (*p >= 'A' && *p <= 'Z')
- *p += 'a' - 'A';
- /* make half of them upper case */
- if (*p >= 'a' && *p <= 'z' && Random() < 0)
- *p -= 'a' - 'A';
- p++;
- } while (--i);
- break;
- #endif
-
- #if BACKWARDS_LETTERS
- case BackwardsLetters:
- /* flip the string front to back */
- inputPtr = (Byte *) theStringPtr + i;
- do {
- *p++ = *inputPtr;
- inputPtr--;
- } while (--i);
- break;
- #endif
-
- #if ACCENTED_VOWELS
- case AccentedVowels:
- /* put an accent mark over each vowel */
- do {
- rand = abs(Random());
- switch (*p) {
- case 'A':
- switch (rand & (4-1)) {
- case 0: *p = 0x80; break;
- case 1: *p = 0x81; break;
- case 2: *p = 0xCB; break;
- case 3: *p = 0xCC; break;
- }
- break;
- case 'E':
- *p = 0x83;
- break;
- case 'O':
- if (Random() < 0)
- *p = 0x85;
- else
- *p = 0xCD;
- break;
- case 'U':
- *p = 0x86;
- break;
- case 'a':
- *p = 0x87 + (rand % 6);
- break;
- case 'e':
- *p = 0x8E + (rand & (4-1));
- break;
- case 'i':
- *p = 0x92 + (rand & (4-1));
- break;
- case 'o':
- *p = 0x97 + (rand % 5);
- break;
- case 'u':
- *p = 0x9C + (rand & (4-1));
- break;
- default:
- break;
- }
- p++;
- } while (--i);
- break;
- #endif
-
- #if NO_VOWELS
- case NoVowels:
- /* remove all vowels */
- inputPtr = (Byte *) theStringPtr + 1;
- do {
- ch = *inputPtr;
- if (ch >= 'A' && ch <= 'Z')
- ch += 'a' - 'A';
- if (ch == 'a' || ch == 'e' || ch == 'i'
- || ch == 'o' || ch == 'u')
- copyOfString[0]--;
- else
- *p++ = *inputPtr;
- inputPtr++;
- } while (--i);
- /* make sure the string length is at least 1 */
- if (copyOfString[0] == 0) {
- copyOfString[0] = 1;
- copyOfString[1] = *((Byte *) theStringPtr + 1);
- }
- break;
- #endif
-
- #if PIG_LATIN
- case PigLatin:
- /* not implemented */
- break;
- #endif
-
- case -1:
- default:
- #if ALWAYS_TWEAK_STRING
- goto TryAgain;
- #endif
- break;
- }
-
- theStringPtr = ©OfString;
- }
-
- DontDoAnything:
-
- /* find our globals */
- pgPtr = (PatchGlobalsPtr) ((long) StartPatchCode -
- sizeof(PatchGlobals));
-
- /* call the real DrawString */
- (*pgPtr->pgOldDS)(theStringPtr);
- }
-
-
- /*************************************************
- * abs
- *
- * Return the absolute value of n.
- ************************************************/
- short
- abs(short n)
- {
- if (n < 0)
- return (-n);
- return (n);
- }
-
-
- /*************************************************
- * EndPatchCode
- *
- * Dummy proc to mark the end of the code for
- * the patches. Make sure all of your patch code
- * is between here and StartPatchCode.
- ************************************************/
- void EndPatchCode()
- {
- }
-